home *** CD-ROM | disk | FTP | other *** search
/ Aminet 31 / Aminet 31 (1999)(Schatztruhe)[!][Jun 1999].iso / Aminet / dev / c / vbccppcsrc.lha / vbcc / pasm / eval.c < prev    next >
C/C++ Source or Header  |  1999-03-07  |  22KB  |  828 lines

  1. /* $VER: pasm eval.c V1.2 (21.10.98)
  2.  *
  3.  * This file is part of pasm, a portable PowerPC assembler.
  4.  * Copyright (c) 1997-98  Frank Wille
  5.  *
  6.  * pasm is freeware and part of the portable and retargetable ANSI C
  7.  * compiler vbcc, copyright (c) 1995-98 by Volker Barthelmann.
  8.  * pasm may be freely redistributed as long as no modifications are
  9.  * made and nothing is charged for it. Non-commercial usage is allowed
  10.  * without any restrictions.
  11.  * EVERY PRODUCT OR PROGRAM DERIVED DIRECTLY FROM MY SOURCE MAY NOT BE
  12.  * SOLD COMMERCIALLY WITHOUT PERMISSION FROM THE AUTHOR.
  13.  *
  14.  *
  15.  * v1.2   (21.10.98) phx
  16.  *        @sdarx and @sdax are recognized and generate a R_PPC_SDAREL16
  17.  *        relocation.
  18.  *        Replaced obsolete R_PPC_TOC16 by real R_PPC_SDAREL16.
  19.  * v1.1e  (19.10.98) phx
  20.  *        Improved hihalf(): >> instead /
  21.  * v1.0   (04.04.98) phx
  22.  *        ADDR16-relocation/xref works for instructions, like addi, cmpi, etc.
  23.  * v0.9   (07.03.98) phx
  24.  *        The EHF-offset for R_REL14 is handled in instructions.c. No need
  25.  *        to increase the return value in makexref() and makereloc().
  26.  * v0.7   (01.01.98) phx
  27.  *        @ha, @h, @l are only allowed at the end of an operand, according
  28.  *        to GNU-as notation. '@' is only allowed as the first character in
  29.  *        a symbol (for @function and @object, for example).
  30.  *        Don't waste memory in makereloc() and makexref() by adding new
  31.  *        nodes to the current section if another pass is required
  32.  *        anyway.
  33.  * v0.5   (11.10.97) phx
  34.  *        getarg() works with \' and \" now.
  35.  * v0.4   (05.07.97) phx
  36.  *        R_PPC_TOC16 and R_PPC_REL14 support in makereloc() and makexref().
  37.  *        "(<term>)@l/h/ha" was not recognized.
  38.  *        A comment introducer '#' was erroneously treated as a macro
  39.  *        parameter in read_macro_params().
  40.  *        Undefined symbols are only automatically declared as externally
  41.  *        defined, if the -x option was given. Otherwise display an
  42.  *        error message.
  43.  *        Implementing backwards-evaluation of an expression in v0.3 was not
  44.  *        very smart (e.g. 4-1+2 => 1(!)) - changed to forward again... ;)
  45.  * v0.3   (20.04.97) phx
  46.  *        Bug in eval_expression() fixed, which sometimes caused the loss
  47.  *        of the last argument of an expression.
  48.  * v0.2   (25.03.97) phx
  49.  *        Writes ELF object for 32-bit PowerPC big-endian. Either absolute
  50.  *        or ELF output format may be selected. ELF is default for all
  51.  *        currently supported platforms. PPCasm supports nine different
  52.  *        relocation types (there are much more...).
  53.  *        Compiles and works also under NetBSD/amiga (68k).
  54.  *        Changed function declaration to 'new style' in all sources
  55.  *        (to avoid problems with '...' for example).
  56.  *        makexref() and makereloc() used wrong offset.
  57.  * v0.1   (11.03.97) phx
  58.  *        First test version with all PowerPC instructions and most
  59.  *        important directives. Only raw, absolute output.
  60.  * v0.0   (21.02.97) phx
  61.  *        File created.
  62.  */
  63.  
  64.  
  65. #define EVAL_C
  66. #include "ppcasm.h"
  67.  
  68.  
  69. char *getsymbol(struct GlobalVars *,char *);
  70. char *getarg(struct GlobalVars *,char *);
  71. char *skipspaces(char *);
  72. char *remquotes(char *);
  73. void checkEOL(char *);
  74. char *skipexpression(struct GlobalVars *,char *);
  75. void read_macro_params(struct GlobalVars *,struct ParsedLine *,
  76.                        struct MacroParams *,char *);
  77. char *getexp(struct GlobalVars *,char *,uint32 *,uint8);
  78. uint32 makereloc(struct GlobalVars *,struct Expression *);
  79. uint32 makexref(struct GlobalVars *,struct Expression *,uint8);
  80. char *getintexp(struct GlobalVars *,char *,uint32 *);
  81. char *eval_expression(struct GlobalVars *,struct Expression *,char *);
  82.  
  83. static uint32 hihalf(struct GlobalVars *,uint32);
  84. static uint32 lohalf(struct GlobalVars *,uint32);
  85. static uint32 read_hex(char *);
  86. static uint32 read_dec(char *);
  87. static uint32 read_oct(char *);
  88. static uint32 read_bin(char *);
  89. static uint32 read_str(char *);
  90.  
  91.  
  92.  
  93. /* table of valid symbol characters, 
  94.    0=invalid, 1=valid in whole symbol, 2=valid, but not as first char */
  95. static uint8 valid_symchars[256] = {
  96.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  97.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  98.   0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,  /* $ . */
  99.   2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,1,  /* 0-9 ? */
  100.   0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,  /* A-O */
  101.   1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,  /* P-Z _ */
  102.   0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,  /* a-o */
  103.   1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,  /* p-z */
  104.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  105.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  106.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  107.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  108.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  109.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  110.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  111.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  112. };
  113.  
  114. /* table of valid argument characters, 
  115.    0=invalid, 1=valid, 2=valid, but indicates string */
  116. static uint8 valid_argchars[256] = {
  117.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  118.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  119.   0,0,2,0,1,0,0,2,0,0,0,0,0,0,1,0,  /* " $ ' . */
  120.   1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,1,  /* 0-9 ? */
  121.   0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,  /* A-O */
  122.   1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,  /* P-Z _ */
  123.   0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,  /* a-o */
  124.   1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,  /* p-z */
  125.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  126.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  127.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  128.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  129.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  130.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  131.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  132.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  133. };
  134.  
  135. /* valid operators */
  136. #define NUMOPS 10
  137. static char valid_operators[NUMOPS] = {
  138.   '+','-','*','/','%','<','>','&','|','^'
  139. };
  140. #define MAXOPPRI 5
  141. static uint8 op_priority[NUMOPS] = {
  142.   4,4,5,5,5,3,3,2,0,1
  143. };
  144.  
  145.  
  146. char *getsymbol(struct GlobalVars *gv,char *s)
  147. /* read a symbol string into gv->strbuf */
  148. {
  149.   uint8 *vsc = valid_symchars;
  150.   char *b = gv->strbuf;
  151.   int bsize = STRBUFSIZE-2;
  152.  
  153.   if (*s == '@') {  /* '@' is allowed as first character */
  154.     *b++ = *s++;
  155.     bsize--;
  156.   }
  157.   if (vsc[(unsigned char)*s] == 1) {  /* first character valid? */
  158.     *b++ = *s++;
  159.     while (vsc[(unsigned char)*s] && bsize--)
  160.       *b++ = *s++;
  161.   }
  162.   *b = 0;
  163.   return (s);
  164. }
  165.  
  166.  
  167. char *getarg(struct GlobalVars *gv,char *s)
  168. /* read next argument into gv->strbuf */
  169. {
  170.   uint8 v,*vac = valid_argchars;
  171.   char c,*b = gv->strbuf;
  172.   int bsize = STRBUFSIZE-1;
  173.  
  174.   if (*s == '@') {  /* '@' is allowed as first character */
  175.     *b++ = *s++;
  176.     bsize--;
  177.   }
  178.   while ((v = vac[(unsigned char)*s]) && bsize--) {
  179.     *b++ = *s++;
  180.     if (v==2) {  /* string? */
  181.       c = *(s-1);
  182.       for (;;) {
  183.         if (bsize--) {
  184.           if (!(*b++ = *s))  /* string can only be terminated by EOL */
  185.             return (s);
  186.         }
  187.         else
  188.           return (s);
  189.         if (*s++ == c) {
  190.           if (*s==c || *(s-2)=='\\') {
  191.             if (bsize--)  /* "", '' \" or \' don't terminate the string */
  192.               *b++ = *s++;
  193.              else
  194.               return (s);
  195.           }
  196.           else
  197.             break;
  198.         }
  199.       }
  200.     }
  201.   }
  202.   *b = 0;
  203.   return (s);
  204. }
  205.  
  206.  
  207. char *skipspaces(char *s)
  208. /* advance string pointer to the first character, which is no white space */
  209. {
  210.   while (*s==' ' || *s=='\t')
  211.     ++s;
  212.   return (s);
  213. }
  214.  
  215.  
  216. char *remquotes(char *s)
  217. /* remove " or ', if present and return new strbuf-pointer */
  218. {
  219.   int len;
  220.   char c = *s;
  221.  
  222.   if (c=='\"' || c=='\'')  /* string is in quotes */
  223.     if (len = strlen(++s) - 1)
  224.       if (s[len] == c)
  225.         s[len] = 0;
  226.   return (s);
  227. }
  228.  
  229.  
  230. void checkEOL(char *s)
  231. /* check for illegal extra characters on line */
  232. {
  233.   s = skipspaces(s);
  234.   if (*s && *s!='#')  /* only comment is allowed as an extra character */
  235.     error(18);  /* extra characters on line */
  236. }
  237.  
  238.  
  239. char *skipexpression(struct GlobalVars *gv,char *s)
  240. {
  241.   char c;
  242.  
  243.   do {
  244.     s = getarg(gv,s);
  245.     s = skipspaces(s);
  246.     c = *s++;
  247.   }
  248.   while (c!=0 && c!='#' && c!=',');
  249.   return (--s);
  250. }
  251.  
  252.  
  253. void read_macro_params(struct GlobalVars *gv,struct ParsedLine *pl,
  254.                        struct MacroParams *mp,char *op)
  255. /* read parameters and store pointers to their first character */
  256. {
  257.   char c;
  258.  
  259.   mp->param[0] = mp->param0;
  260.   if (pl->branch_hint)
  261.     mp->param0[0] = pl->branch_hint>0 ? '+